#include <stdio.h>
#include "TI_Command.h"
#include "TI_FS_Command.h"

CTICommand *g_pCTICommand;

//EXTERN_C void FS_TEST();

ECode CTICommand::Control(
    /* [in] */ Handle32 nControlCode,
    /* [in] */ const MemoryBuf & inBuffer,
    /* [out] */ MemoryBuf * pOutBuffer,
    /* [out] */ IEvent * * ppCompletionEvent)
{
    ECode ec = NOERROR;

    switch (nControlCode) {
        case 0:
//            FS_TEST();
//            break;
//            nu_InitTICommandTestAndRun(0);
//            break;

            if (inBuffer.GetPayload() == NULL) {
                kprintf("CTICommand E_INVALID_ARGUMENT\n");
                ec = E_INVALID_ARGUMENT;
            }
            else {
                kprintf("CTICommand cmd:%d.\n", *(int *)inBuffer.GetPayload());
                nu_InitTICommandTestAndRun(*(int *)inBuffer.GetPayload());
            }
            break;
        default :
            ec = E_NOT_IMPLEMENTED;
            break;
    }

    return ec;
}

void CTICommand::Dispose()
{
    delete this;
}

EXTERN_C int TICommandCameraInit();
EXTERN_C int TICommandCameraBeginPreview();
EXTERN_C int TICommandCameraStopPreview();
EXTERN_C int TICommandCameraSnapshot();
EXTERN_C int TICommandCameraDele();


void DoCommand(TI_COMMNAD cmd, PVOID pInData, PVOID pOutData)
{
//    kprintf("TI_COMMNAD cmd:%d, pInData:0x%x, pOutData:0x%x\n",
//    cmd, (int *)pInData, (int *)pOutData);

    static int s_fs_flag = 0;
    if(0 == s_fs_flag){
        TICommandFsInit();
        s_fs_flag = 1;
    }
    switch (cmd) {
        case TI_CMD_CameraInit:
            *(int *)pOutData = TICommandCameraInit();
            break;
        case TI_CMD_CameraBeginPreview:
            *(int *)pOutData = TICommandCameraBeginPreview();
            break;
        case TI_CMD_CameraStopPreview:
            *(int *)pOutData = TICommandCameraStopPreview();
            break;
        case TI_CMD_CameraSnapshot:
            *(int *)pOutData = TICommandCameraSnapshot();
            break;
        case TI_CMD_CameraDele:
            *(int *)pOutData = TICommandCameraDele();
            break;

        case TI_CMD_Fs_Init:
            *(int *)pOutData = TICommandFsInit();
            break;

        case TI_CMD_Fs_DeInit:
            *(int *)pOutData = TICommandFsDeInit();
            break;
        case TI_CMD_Fs_Open:
        {
            typedef struct{
                char* fullPathFileName;
                int flags;
                int *pFd;
            }CMD_FS_OPEN;
            int ret;
            CMD_FS_OPEN *pInput = (CMD_FS_OPEN*)pInData;
//            kprintf("TI_CMD_Fs_Open in.\n");
            ret = TICommandFsOpen(pInput->fullPathFileName,
                                               pInput->flags,
                                               pInput->pFd);
            *(int *)pOutData = ret;
//            kprintf("1TI_CMD_Fs_Open out.\n");
        }
            break;
        case TI_CMD_Fs_Close:
            *(int *)pOutData = TICommandFsClose(*(int *)pInData);
            break;
        case TI_CMD_Fs_Read:
        {
            typedef struct{
                int fd                    ;
                void* buf                 ;
                unsigned int nSize        ;
                unsigned int *pnReadedSize;
            }CMD_FS_READ;
            CMD_FS_READ *pInput = (CMD_FS_READ*)pInData;
            *(int *)pOutData = TICommandFsRead ( pInput->fd,
                                                 pInput->buf,
                                                 pInput->nSize,
                                                 pInput->pnReadedSize);
        }
            break;
        case TI_CMD_Fs_Write:
        {
            typedef struct{
                int fd                    ;
                void* buf                 ;
                unsigned int nSize        ;
                unsigned int *pnWritedSize;
            }CMD_FS_WRITE;
            CMD_FS_WRITE *pInput = (CMD_FS_WRITE*)pInData;
            *(int *)pOutData = TICommandFsWrite(pInput->fd,
                                                pInput->buf,
                                                pInput->nSize,
                                                pInput->pnWritedSize);
        }
            break;
        case TI_CMD_Fs_Remove:
            *(int *)pOutData = TICommandFsRemove( (char *)pInData );
            break;
        case TI_CMD_Fs_Flush:
            *(int *)pOutData = TICommandFsFlush(*(int *)pInData);
            break;
        case TI_CMD_Fs_Stat:
        {
            typedef struct{
                char* fullPathName;
                BTFsStat* fileStat;
            }CMD_FS_STAT;
            CMD_FS_STAT *pInput = (CMD_FS_STAT*)pInData;
            *(int *)pOutData = TICommandFsStat(pInput->fullPathName,
                                               pInput->fileStat );
        }
            break;
        case TI_CMD_Fs_Tell:
        {
            typedef struct{
                int fd;
                unsigned int *curPosition;
            }CMD_FS_TELL;
            CMD_FS_TELL *pInput = (CMD_FS_TELL*)pInData;
            *(int *)pOutData = TICommandFsTell(pInput->fd,
                                               pInput->curPosition);
        }
            break;
        case TI_CMD_Fs_Seek:
        {
            typedef struct{
                int fd;
                int offset;
                BtFsSeekOrigin from;
            }CMD_FS_SEEK;
            CMD_FS_SEEK *pInput = (CMD_FS_SEEK*)pInData;
            *(int *)pOutData = TICommandFsSeek(pInput->fd,
                                               pInput->offset,
                                               pInput->from);
        }
            break;
        case TI_CMD_Fs_Mkdir:
            *(int *)pOutData = TICommandFsMkdir((char *)pInData);
            break;
        case TI_CMD_Fs_Rmdir:
            *(int *)pOutData = TICommandFsRmdir( (char *)pInData );
            break;
        case TI_CMD_Fs_OpenDir:
        {
            typedef struct{
                char *dirFullPathName;
                int *dirDesc;
            }CMD_FS_OPEN_DIR;
            CMD_FS_OPEN_DIR *pInput = (CMD_FS_OPEN_DIR*)pInData;
            *(int *)pOutData = TICommandFsOpenDir(pInput->dirFullPathName,
                                                  pInput->dirDesc );
        }
            break;
        case TI_CMD_Fs_ReadNextDir:
        {
            typedef struct{
                int dirDesc;
                char *fileName;
            }CMD_FS_READ_NEXT_DIR;
            CMD_FS_READ_NEXT_DIR *pInput = (CMD_FS_READ_NEXT_DIR*)pInData;
            *(int *)pOutData = TICommandFsReadNextDir(pInput->dirDesc,
                                                      pInput->fileName );
        }
            break;
        case TI_CMD_Fs_CloseDir:
            *(int *)pOutData = TICommandFsCloseDir( *(int *)pInData );
            break;
        case TI_CMD_Fs_Rename:
        {
            typedef struct{
                char *fullPathOldName;
                char *fullPathNewName;
            }CMD_FS_OPEN_RENAME;
            CMD_FS_OPEN_RENAME *pInput = (CMD_FS_OPEN_RENAME*)pInData;
            *(int *)pOutData = TICommandFsRename(pInput->fullPathOldName,
                                                 pInput->fullPathNewName );
        }
            break;
        default:
            kprintf("DoTICommandThread: Invalid Command");
            break;
    }
}

Int32 DoTICommandThread(void *p)
{
    WaitResult wr;
    EventState state;
    PVOID pInData;
    PVOID pOutData;
    TI_COMMNAD cmd;


    while(1){
        g_pCTICommand->m_event.Wait(&wr, &state);
        nu_GetCommandMsg(&cmd, &pInData, &pOutData);
        DoCommand(cmd, pInData, pOutData);
        nu_FinishCommand();
    }

    return 1;
}


void **g_TICommandApiForZener;

EXTERN IDeviceDriver * CDECL CreateTICommand(uint_t uDeviceNo, void *pvParameter)
{
    ECode ec;
    CTICommand* TICommand = new CTICommand;
    if (!TICommand) {
        DRV_EXPRESSION(ERRORLEVEL, kprintf("CreateTICommand Not enough memory\n"));
        return NULL;
    }
    g_pCTICommand = TICommand;

    g_TICommandApiForZener = nu_TICommand_GetAPIs();
    if(NULL == g_TICommandApiForZener){
        kprintf("Create CreateTICommand Failed!\n");
        goto ERR;
    }

    ec = DzCreateKernelThread(DoTICommandThread,
                              NULL,
                              CreateThreadFlag_System,
                              ThreadPriorityRank_SoftRealTime,
                              &TICommand->m_pIThread);
    if(FAILED(ec)){
        kprintf("CreateTICommand thread failed!\n");
        goto ERR;
        return NULL;
    }

    if(0 != nu_InitTICommand((Uint32)&TICommand->m_event)){
        DRV_EXPRESSION(ERRORLEVEL, kprintf("CreateTICommand nu_InitTICommand\n"));
        goto ERR;
    }

    TICommand->AddRef();
    kprintf("Create TICommand OK!\n");
    return (IDeviceDriver *)TICommand;

ERR:
    if(NULL != TICommand->m_pIThread){
        TICommand->m_pIThread->Abort();
    }

    g_pCTICommand = NULL;

    delete TICommand;

    return NULL;

}




